/********************************************************************
	platform:	
	author:		kevin
	copyright:	All rights reserved.
	purpose:	
	brief:		
*********************************************************************/

#pragma once

#include <lib_net/lib_tcp_client.h>
#include <lib_log.h>
#include <lib_util.h>
#include <lib_proto/lib_cmd_map.h>
#include <lib_err_code.h>
#include <lib_proto/lib_msgbuf.h>
#include <service_if.h>

#include "libmysql_iface.h"
#include "libmysql_proto_header.h"

class Cfunc_route;

class Cfunc_route_base : public el_async::client_base_t<Cfunc_route>
{
	PROTECTED_R(el::lib_mysql_if*, db);//db 连接
	PROTECTED_R(uint32_t, cmd);/*用于保存当前命令号，只是为了方便 */
public:
	Cfunc_route_base(el::lib_mysql_if* db){
		this->db = db;
		this->cmd = 0;
	}
	virtual ~Cfunc_route_base(){}
	virtual int do_handle_dispatcher(const void* data, uint32_t len, el::lib_tcp_peer_info_t* peer_fd_info){
		el::lib_recv_data_cli_t in(data);
		this->peer = peer_fd_info;
		in>>this->head.magic>>this->head.len>>this->head.op>>this->head.param>>this->head.seq>>this->head.ret;
		
		DEBUG_LOG("c=>[body_len:%u, cmd:%#x, seq:%u, ret:%#x, uid:%u, fd:%d, pkglen:%d]",
			this->head.len, this->head.op, this->head.seq, this->head.ret, this->head.param, this->peer->get_fd(), len);

		TRACE_MSG_HEX_LOG(data, len);

		this->p_cmd_item = this->cmd_map.get(this->head.op);
		this->ret = 0;
		this->cmd = this->head.op;
		if (NULL == this->p_cmd_item){
			ERROR_LOG("cli handle empty [uid:%u, cmd:%#x]", this->head.param, this->head.op);
			this->ret = el::ERR_SYS::UNDEFINED_CMD;
		} else {
			//还原对象
			this->p_cmd_item->msg_out->init();
			this->ret = this->restore_msg(data, this->p_cmd_item->msg_in, this->p_cmd_item->msg_out);
			if (0 == ret){
#ifdef SHOW_ALL_LOG
				TRACE_MSG_LOG("c======>");
#endif
				this->ret = this->handle_msg(this->p_cmd_item->func, this->p_cmd_item->msg_in, this->p_cmd_item->msg_out);
				if (0 != this->ret){
					this->db->db_rollback();
				}
				
				//提交数据
				this->db->db_commit();
			}
		}
		if (0 != this->ret){
			this->do_s2err(this->peer, this->head, this->ret);
		} else {
			this->s2peer_msg(this->peer, this->head, p_cmd_item->msg_out);
		}
		return this->ret;
	}
	virtual int do_s2err(el::lib_tcp_peer_info_t* peer_fd_info, 
		el::lib_proto_head_t& head, uint32_t err){
			head.magic = PACKET_MAGIC_D;
			head.ret = err;
			ERROR_LOG("[uid:%u, cmd:%#x, len:%u, seq:%u, ret:%#x]", 
				head.param, head.op, head.len, head.seq, head.ret);
			return s2peer_msg(peer_fd_info, &head);
	}
};


